package org.spbsu.apco.server.taskset.sample;

import org.spbsu.apco.common.data.impl.Matrix;
import org.spbsu.apco.common.task.impl.matrix.MatrixConstructionTask;
import org.spbsu.apco.common.task.impl.matrix.RowColumnMultiplicationTask;
import org.spbsu.apco.common.task.impl.matrix.RowConstructionTask;
import org.spbsu.apco.server.taskset.BaseTaskSet;

import java.util.ArrayList;
import java.util.List;

/**
 * User: ortemij
 * Date: 05.01.13
 * Time: 21:33
 */
public class MatrixMultiplicationTaskSet extends BaseTaskSet {

    private final int n;
    private final int m;
    private final int r;

    /**
     * A[n x m] * B[m x r]
     */
    public MatrixMultiplicationTaskSet(int n, int m, int r) {
        this.n = n;
        this.m = m;
        this.r = r;
    }

    public void initializeTasks() {
        Matrix a = new Matrix(n, m);
        Matrix b = new Matrix(r, m); // transponated
        a.initRandom();
        b.initRandom();

        final MatrixConstructionTask matrixConstructionTask = new MatrixConstructionTask();
        for (int j = 0; j < r; j++) {
            double[] column = b.getRow(j);
            RowConstructionTask rowConstructionTask = new RowConstructionTask();
            for (int i = 0; i < n; i++) {
                double[] row = a.getRow(i);
                final RowColumnMultiplicationTask task = new RowColumnMultiplicationTask();
                rowConstructionTask.addSubTasks(task);
                addLeafTask(task, merge(row, column));
            }
            matrixConstructionTask.addSubTasks(rowConstructionTask);
            addTask(rowConstructionTask);
        }
        addTask(matrixConstructionTask);
    }

    private static List<Double> merge(double[] row, double[] column) {
        List<Double> merged = new ArrayList<Double>(row.length + column.length);
        for (int i = 0; i < row.length; i++) {
            merged.add(row[i]);
            merged.add(column[i]);
        }
        return merged;
    }
}
